package com.unknownman.block.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.lianziyou.chain.common.api.CommonPage;
import com.lianziyou.chain.common.utils.ConvertContractValue;
import com.unknownman.block.constants.ChainContractConstants;
import com.unknownman.block.entity.TContractConfig;
import com.unknownman.block.entity.TContractLogs;
import com.unknownman.block.entity.TNft;
import com.unknownman.block.entity.TNftTransRecord;
import com.unknownman.block.mapper.TNftMapper;
import com.unknownman.block.service.TContractConfigService;
import com.unknownman.block.service.TNftService;
import com.unknownman.block.service.TNftTransRecordService;
import org.cloud.utils.DataDimensionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.web3j.utils.Numeric;

import java.util.List;

/**
* <p>
    * NFT列表 服务实现类
    * </p>
*
* @author xhy
* @since 2021-10-15
*/
@Service
public class TNftServiceImpl extends ServiceImpl<TNftMapper, TNft> implements TNftService {

    @Autowired
    private TContractConfigService contractConfigService;
    @Autowired
    private TNftTransRecordService nftTransRecordService;


    @Override
    public  CommonPage<TNft> findListByPage(Integer page, Integer limit, String orderBy, QueryWrapper<TNft> queryWrapper){

        if (StringUtils.isEmpty(orderBy)){
            PageHelper.startPage(page, limit);
        }else {
            PageHelper.startPage(page, limit, orderBy);
        }
        List<TNft> list = baseMapper.selectList(queryWrapper);
        return CommonPage.restPage(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveByLog(TContractLogs logs) {
        if (!logs.getFirstTopic().equalsIgnoreCase(ChainContractConstants.TRANSFER_EVENT_NAME)){
            return false;
        }
        TContractConfig contractConfig = contractConfigService.getById(logs.getContractConfigId());

        String from = logs.getSecondTopic();
        String to = logs.getThirdTopic();
        String tokenIdStr = logs.getFourthTopic();
        if (StringUtils.isEmpty(logs.getLogData()) || StringUtils.isEmpty(to) || StringUtils.isEmpty(tokenIdStr)){
            return false;
        }
        from = ConvertContractValue.convertToAddress(from);
        to = ConvertContractValue.convertToAddress(to);
        Long tokenId = Numeric.decodeQuantity(tokenIdStr).longValue();

        Long nftId = 0L;
        if (!from.equals(to)){
            TNft nft = getTokenByContractIdAndTokenId(contractConfig.getContractConfigId(), tokenId);
            if (nft == null){
                TNft _nft = new TNft();
                _nft.setContractConfigId(contractConfig.getContractConfigId());
                _nft.setTokenId(tokenId);
                _nft.setFounTime(logs.getBlockTimestamp());
                _nft.setOwnerAddress(to);
                _nft.setPreOwnerAddress(from);
                boolean save = getBaseMapper().insert(_nft) > 0;
                Assert.isTrue(save, "saveByLog： 新增NFT信息失败, hash: " + logs.getTransHash());
                nftId = _nft.getNftId();
            }else {
                int i = getBaseMapper().updateNftOwner(contractConfig.getContractConfigId(), tokenId, to, nft.getTransCount());
                Assert.isTrue(i > 0, "saveByLog: 更新NFT所属人失败, hash: " + logs.getTransHash());
                nftId = nft.getNftId();
            }
        }

        TNftTransRecord nftTransRecord = new TNftTransRecord();
        nftTransRecord.setContractConfigId(contractConfig.getContractConfigId());
        nftTransRecord.setNftId(nftId);
        nftTransRecord.setTokenId(tokenId);
        nftTransRecord.setTransactionHash(logs.getTransHash());
//        nftTransRecord.setBlockNumber();
        nftTransRecord.setFromAddress(from);
        nftTransRecord.setToAddress(to);
        nftTransRecord.setBlockTimestamp(logs.getBlockTimestamp());
        boolean save = nftTransRecordService.save(nftTransRecord);
        Assert.isTrue(save, "saveByLog: 保存NFT转账记录失败, hash: " + logs.getTransHash());
        return true;
    }

    @Override
    public TNft getTokenByContractIdAndTokenId(Long contractConfigId, Long tokenId) {
        QueryWrapper<TNft> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("contract_config_id", contractConfigId);
        queryWrapper.eq("token_id", tokenId);
        return getOne(queryWrapper);
    }
}
